<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Web高级开发 | Advanced Web Development Course</title>
    <link
      href="https://fonts.googleapis.com/css?family=Heebo:300,400"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="../../css/main.css" />
    <link rel="stylesheet" href="../../css/tabs.css" />
    <script src="../../js/uikit.js"></script>
    <link href="../../css/prism.css" rel="stylesheet" />
    <script src="../../js/prism.js"></script>
  </head>

  <body>
    <div
      data-uk-sticky="animation: uk-animation-slide-top; sel-target: .uk-navbar-container; cls-active: uk-navbar-sticky; cls-inactive: uk-navbar-transparent; top: 300"
    >
      <nav class="uk-navbar-container pt-2 pb-2">
        <div class="uk-container">
          <div data-uk-navbar>
            <div class="uk-navbar-left">
              <a
                class="uk-navbar-item uk-logo uk-visible@m"
                href="../../index.html"
                >Web高级开发课程</a
              >
              <a
                class="uk-navbar-tuk-containeroggle uk-hidden@m"
                href="#offcanvas-docs"
                data-uk-toggle
                ><span data-uk-navbar-toggle-icon></span>
                <span class="uk-margin-small-left">目录</span></a
              >
              <ul class="uk-navbar-nav uk-visible@m">
                <li><a href="../../index.html">文档</a></li>
              </ul>
            </div>
            <div class="uk-navbar-center uk-hidden@m">
              <a class="uk-navbar-item uk-logo" href="../../index.html"
                >Web高级开发课程</a
              >
            </div>
          </div>
        </div>
      </nav>
    </div>

    <div class="uk-section">
      <div class="uk-container">
        <div class="uk-grid-large" data-uk-grid>
          <div class="sidebar-fixed-width uk-visible@m">
            <div class="sidebar-docs uk-position-fixed uk-margin-top">
              <h5>关于这门课</h5>
              <ul class="uk-nav uk-nav-default doc-nav">
                <li><a href="../../index.html">大纲</a></li>
              </ul>
              <h5>章节</h5>
              <ul class="uk-nav uk-nav-default doc-nav">
                <li><a href="../01.html">第1章 - Spring基础</a></li>
                <li><a href="../02.html">第2章 - Spring中的Bean</a></li>
                <li><a href="../03.html">第3章 - Spring AOP</a></li>
                <li><a href="../04.html">第4章 - Spring的事物管理</a></li>
                <li><a href="../05.html">第5章 - 初识MyBatis</a></li>
                <li><a href="../06.html">第6章 - MyBatis的核心配置</a></li>
                <li><a href="../07.html">第7章 - MyBatis的高级应用</a></li>
                <li><a href="../08.html">第8章 - Spring MVC入门</a></li>
                <li><a href="../09.html">第9章 - Spring MVC数据绑定</a></li>
                <li><a href="../10.html">第10章 - Spring MVC拦截器</a></li>
                <li><a href="../11.html">第11章 - Spring Boot基础</a></li>
                <li><a href="../12.html">第12章 - Spring Boot的Web开发</a></li>
                <li>
                  <a href="../13.html">第13章 - Spring Boot的数据库连接</a>
                </li>
                <li><a href="../14.html">第14章 - 框架整合</a></li>
              </ul>
              <h5>实验课</h5>
              <ul class="uk-nav uk-nav-default doc-nav">
                <li><a href="./code-01.html">01</a></li>
                <li><a href="./code-02.html">02</a></li>
                <li class="uk-active"><a href="./code-03.html">03</a></li>
                <li><a href="./code-04.html">04</a></li>
                <li><a href="./code-05.html">05</a></li>
                <li><a href="./code-06.html">06</a></li>
                <li><a href="./code-07.html">07</a></li>
                <li><a href="./code-08.html">08</a></li>
                <li><a href="./code-09.html">09</a></li>
                <li><a href="./code-10.html">10</a></li>
                <li><a href="./code-11.html">11</a></li>
                <li><a href="./code-12.html">12</a></li>
              </ul>
            </div>
          </div>
          <div class="uk-width-1-1 uk-width-expand@m">
            <article class="uk-article">
              <h3>JDBC和事务管理实验课内容</h3>
              <div class="tabs">
                <div class="tab-2">
                  <label for="tab2-1">JDBC</label>
                  <input
                    id="tab2-1"
                    name="tabs-three"
                    type="radio"
                    checked="checked"
                  />
                  <div>
                    <p>
                      1. 在pom.xml文件的dependencies里添加下面的依赖
                      <br>
                      然后右键当前项目 --> Maven --> update project，让maven导入相应的jar包
                    </p>
                    <pre class="line-numbers">
<code class="language-markup">&lt;dependency>
  &lt;groupId>org.springframework&lt;/groupId&gt;
  &lt;artifactId>spring-jdbc&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency>
  &lt;groupId>mysql&lt;/groupId&gt;
  &lt;artifactId>mysql-connector-java&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>


<p>
  2. 配置xml文件，<a href="../../files/applicationContext.xml" download>点击这里下载</a>基本xml文件，放到resources目录下，然后加入下面的代码。
  <br>
  其中spring_db 是数据库schema的名字，这个可根据实际情况变更。
</p>
<pre class="line-numbers">
<code class="language-markup">&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
    &lt;!-- 连接数据库驱动 --&gt;
    &lt;property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/&gt;
    &lt;!-- 连接数据库的url --&gt;
    &lt;property name="url" value="jdbc:mysql://localhost:3306/spring_db?serverTimezone=UTC"/&gt;
    &lt;!-- 连接数据库用户名 --&gt;
    &lt;property name="username" value="root"/&gt;
    &lt;!-- 连接数据库密码 --&gt;
    &lt;property name="password" value="root"/&gt;
&lt;/bean&gt; 

&lt;!-- 配置jdbc模板/工具对象 --&gt;
&lt;bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"&gt;
  &lt;!-- 默认必须使用数据源 --&gt;
  &lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;
</code></pre>


<p>
  3. 创建一个类，在里面写main方法，用Spring的方式创建新数据表，取名叫users（可以根据需要更改）
</p>
<pre class="line-numbers">
<code class="language-java">  ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
  JdbcTemplate jdbcTemplate = (JdbcTemplate) ac.getBean("jdbcTemplate");
  // 创建表
  jdbcTemplate.execute("create table users(" + 
      "id int primary key auto_increment," + 
      "username varchar(40)," + 
      "password varchar(40)," + 
      "balance numeric(10, 2))");
</code></pre>

<p>
  4. 创建User类
  <br>
  主要包含id, username, password 和 balance(存款)，代码如下。
</p>
<pre class="line-numbers">
<code class="language-java">public class User {
	private int id;
	private String username;
	private String password;
	private double balance;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getPassword() {
		return password;
	}
	public void setBalance(double balance) {
		this.balance = balance;
	}
	public double getBalance() {
		return balance;
	}
	@Override
	public String toString() {
		return "Account [name=" + username + ", password=" + password + "]";
	}
}
</code></pre>

<p>
  5. 增加一个用户
  <br><br>
  创建UserDaoImpl类
  <br>
  首先添加jdbcTemplate依赖和setter方法
</p>
<pre class="line-numbers">
<code class="language-java">public class UserDaoImpl {  
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
      this.jdbcTemplate = jdbcTemplate;
    }
}
</code></pre>
<p>
  再添加addUser方法
</p>
<pre class="line-numbers">
<code class="language-java">    public int addUser(User user) {
      String sql = "insert into users(username, password, balance) value(?,?,?)";
      Object[] obj = new Object[] {
          user.getUsername(),
          user.getPassword(),
          user.getBalance(),
      };
      int num = this.jdbcTemplate.update(sql, obj);
      return num;
    }
</code></pre>

<p>
  这时候你的UserDaoImpl类应该大体长这个样子
</p>
<pre class="line-numbers">
<code class="language-java">public class UserDaoImpl {
  
    private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public int addUser(User user) {
		String sql = "insert into users(username, password, balance) value(?,?,?)";
		Object[] obj = new Object[] {
			user.getUsername(),
            user.getPassword(),
            user.getBalance(),
        };
		int num = this.jdbcTemplate.update(sql, obj);
		return num;
    }
}
</code></pre>

<p>
  然后在applicationContext.xml文件里配置一下UserDaoImpl
</p>
<pre class="line-numbers">
<code class="language-xml">&lt;bean id="userDaoImpl" class="com.qust.jdbc.UserDaoImpl"&gt;
  &lt;!-- 默认必须使用数据源 --&gt;
  &lt;property name="jdbcTemplate" ref="jdbcTemplate"/&gt;
&lt;/bean&gt;</code></pre>
<p>
  6. 回到main方法中，加入下面代码，用Spring的方式生成userDaoImpl对象
</p>
<pre class="line-numbers">
<code class="language-java">//用Spring的方式生成userDaoImpl对象
UserDaoImpl userDaoImpl = (UserDaoImpl)ac.getBean("userDaoImpl");
</code></pre>
<p>
  7. 再加入下面代码，设置新的User
</p>
<pre class="line-numbers">
<code class="language-java">  // 添加新User
  User user = new User();
  user.setUsername("Tom");
  user.setPassword("123");
  user.setBalance(5000);
  int result = userDaoImpl.addUser(user);
  if(result > 0) {
    System.out.println("成功插入" + result + "条数据。");
  } else {
    System.out.println("操作失败。");
  }
</code></pre>

<p>
  8. 运行main方法，让数据库的users表中添加Tom。
  <br>
  成功运行后，就能看到下面的打印结果和users表中的新数据。
</p>
<img src="../../images/lab03/lab-3-1.JPG" alt="lab-3-1">
<br>
<img src="../../images/lab03/lab-3-2.JPG" alt="lab-3-2">

<p>
  9. 更新user的密码
  <br>
  在userDaoImpl里加入下面代码
<pre class="line-numbers"><code class="language-java">// 更新User
public int updateUser(User user) {
  String sql="update users set username=?, password=? where id=?";
  Object[] obj = new Object[] {
      user.getUsername(),
      user.getPassword(),
      user.getId(),
  };
  int num = this.jdbcTemplate.update(sql, obj);
  return num;
}
  </code></pre>
  注释掉第7步中的代码，在main方法里添加下面代码，然后运行，让Tom的密码变成456
</p>
<pre class="line-numbers"><code class="language-java">  // 更新User
  User user = new User();
  user.setId(1);
  user.setUsername("Tom");
  user.setPassword("456");
  int result = userDaoImpl.updateUser(user);
  if(result > 0) {
    System.out.println("成功更新" + result + "条数据。");
  } else {
    System.out.println("更新失败。");
  }
</code></pre>

<p>
  10. 删除user
  <br><br>
  在userDaoImpl里加入下面代码
 
</p>
<pre class="line-numbers"><code class="language-java">// 删除User  
public int deleteUser(int id) {
  String sql="delete from users where id=?";
  int num = this.jdbcTemplate.update(sql, id);
  return num;
}</code></pre>
<p>注释掉第9步main中的代码，在main方法里添加下面代码，然后运行，删除Tom</p>
<pre class="line-numbers">
<code class="language-java">  // 删除User
  int result = userDaoImpl.deleteUser(1); // 删除 by ID
  if(result > 0) {
    System.out.println("成功删除" + result + "条数据。");
  } else {
    System.out.println("删除失败。");
  }
</code></pre>

<p>
  11. 在UserDaoImpl里添加查找单个user和查找所有users的方法
</p>
<pre class="line-numbers"><code class="language-java">public User findUserById(int id) {
  String sql = "select * from users where id=?";
  RowMapper<User> rowMapper = new BeanPropertyRowMapper<User>(User.class); // 实体属性行映射
  //sping中的RowMapper可以将数据中的每一行数据封装成用户定义的类。
  return (User) this.jdbcTemplate.queryForObject(sql, rowMapper, id);
}

public List<User> findAllUsers() {
  String sql = "select * from users";
  RowMapper<User> rowMapper = new BeanPropertyRowMapper<User>(User.class);
  return this.jdbcTemplate.query(sql, rowMapper);
}</code></pre>
<p>然后在main方法中调用，看打印出来的内容</p>
<pre class="line-numbers">
<code class="language-java">  // 通过ID查询User
  User user = userDaoImpl.findUserById(2);
  System.out.println(user);
  
  // 查询所有Users
  List<User> users = userDaoImpl.findAllUsers();
  System.out.println(users);
</code></pre>





                  </div>
                </div>
                <div class="tab-2">
                  <label for="tab2-2">事务管理</label>
                  <input id="tab2-2" name="tabs-three" type="radio" />
                  <div>
                    <p>
                      I. 用xml配置的方式
                    </p>
                    <p>
                      1. 在pom.xml里加入下面代码，然后右键当前项目-->Maven-->udpate project，让maven导入相应的jar包
                    </p>
    <pre class="line-numbers"><code class="language-xml">&lt;dependency&gt;
  &lt;groupId&gt;org.aspectj&lt;/groupId&gt;
    &lt;artifactId&gt;aspectjweaver&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.springframework&lt;/groupId&gt;
    &lt;artifactId&gt;spring-tx&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>

<p>
  在之前的xml文件里加入事务管理需要的命名空间tx
</p>
<pre class="line-numbers"><code class="language-xml">xmlns:tx="http://www.springframework.org/schema/tx"

// 下面的内容加到xsi:schemaLocation里
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
</code></pre>



                    <p>
                      在之前的xml文件里加入下面的内容
                    </p>
                    <pre class="line-numbers"><code class="language-xml">&lt;!-- XML方式的声明式事务 --&gt;
&lt;!-- 配置事务管理器，依赖于数据源 --&gt;
&lt;bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
  &lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;

&lt;!-- 配置通知/增强 需要编写对切入点和具体执行事务细节 --&gt;
&lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;
  &lt;tx:attributes&gt;
    &lt;tx:method name="*" /&gt;
  &lt;/tx:attributes&gt;
&lt;/tx:advice&gt;

&lt;!-- 织入 --&gt;
&lt;aop:config&gt;
  &lt;aop:pointcut id="txPointCut" expression="execution(* com.qust.jdbctx.*.*(..))" /&gt;
  &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"&gt;&lt;/aop:advisor&gt;
&lt;/aop:config&gt;</code></pre>


<p>
  2. 在UserDaoImpl里添加下面的方法，注意这里加个自杀式报错代码"int i = 1/0;"
</p>
<pre class="line-numbers"><code class="language-java">public void transfer(String sender, String receiver, int money) {
  this.jdbcTemplate.update("update users set balance= balance-? where username=?", money, sender);
  int i = 1/0;
  this.jdbcTemplate.update("update users set balance= balance+? where username=?", money, receiver);
  System.out.println("转账成功");
}</code></pre>

<p>
  3. 在main方法中添加下面的代码并运行，
  让Tom <img src="../../images/lab03/tom.jpg" alt="tom" width="50px"> 
  给Jerry <img src="../../images/lab03/jerry.jpg" alt="jerry" width="50px"> 转500块钱。
  <br>
  由于有"int i = 1/0;"，所以会报错，数据库内的数据不会发生变化，这样咱们就说事务被控制住了。
</p>
<pre class="line-numbers"><code class="language-java">userDaoImpl.transfer("Tom", "Jerry", 500);</code></pre>


<p>
  4. 在UserDaoImpl里把这段代码"int i = 1/0;"注释掉再运行main方法就一切正常了
  <br>
  <img src="../../images/lab03/successful.JPG" alt="">
</p>


<p>
  II. 用注解的方式
</p>
<p>
  5. 把第1步里的配置代码换成下面的内容
</p>
<pre class="line-numbers"><code class="language-xml">&lt;!-- XML方式的声明式事务 --&gt;
&lt;!-- 配置事务管理器，依赖于数据源 --&gt;
&lt;bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
  &lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;

&lt;tx:annotation-driven transaction-manager="transactionManager" /&gt;	
</code></pre>

<p>
  6. 在UserDaoImpl里的transfer方法头上加入下面的代码
<pre class="line-numbers"><code class="language-java">@Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.DEFAULT, readOnly=false)</code></pre>
所以现在的transfer方法应该长这样
<pre class="line-numbers"><code class="language-java">@Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.DEFAULT, readOnly=false)
public void transfer(String sender, String receiver, int money) {
  this.jdbcTemplate.update("update users set balance= balance-? where username=?", money, sender);
  int i = 1/0;
  this.jdbcTemplate.update("update users set balance= balance+? where username=?", money, receiver);
  System.out.println("转账成功");
}</code></pre>
</p>

<p>7. 再运行main方法还是会报错，因为有"int i = 1/0;"的存在。注释掉再运行就能正常转账了。</p>

                  </div>
                </div>
              </div>
            </article>
          </div>
        </div>
      </div>
    </div>

    <div id="offcanvas-docs" data-uk-offcanvas="overlay: true">
      <div class="uk-offcanvas-bar">
        <button class="uk-offcanvas-close" type="button" data-uk-close></button>
        <h5 class="uk-margin-top">关于这门课</h5>
        <ul class="uk-nav uk-nav-default doc-nav">
          <li><a href="../indext.html">大纲</a></li>
        </ul>
        <h5 class="uk-margin-top">章节</h5>
        <ul class="uk-nav uk-nav-default doc-nav">
          <li><a href="../01.html">第1章 - Spring基础</a></li>
          <li><a href="../02.html">第2章 - Spring中的Bean</a></li>
          <li><a href="../03.html">第3章 - Spring AOP</a></li>
          <li><a href="../04.html">第4章 - Spring的事物管理</a></li>
          <li><a href="../05.html">第5章 - 初识MyBatis</a></li>
          <li><a href="../06.html">第6章 - MyBatis的核心配置</a></li>
          <li><a href="../07.html">第7章 - MyBatis的高级应用</a></li>
          <li><a href="../08.html">第8章 - Spring MVC入门</a></li>
          <li><a href="../09.html">第9章 - Spring MVC数据绑定</a></li>
          <li><a href="../10.html">第10章 - Spring MVC拦截器</a></li>
          <li><a href="../11.html">第11章 - Spring Boot基础</a></li>
          <li><a href="../12.html">第12章 - Spring Boot的Web开发</a></li>
          <li><a href="../13.html">第13章 - Spring Boot的数据库连接</a></li>
          <li><a href="../14.html">第14章 - 框架整合</a></li>
        </ul>
        <h5>实验课</h5>
        <ul class="uk-nav uk-nav-default doc-nav">
          <li><a href="./code-01.html">01</a></li>
          <li><a href="./code-02.html">02</a></li>
          <li class="uk-active"><a href="./code-03.html">03</a></li>
          <li><a href="./code-04.html">04</a></li>
          <li><a href="./code-05.html">05</a></li>
          <li><a href="./code-06.html">06</a></li>
          <li><a href="./code-07.html">07</a></li>
          <li><a href="./code-08.html">08</a></li>
          <li><a href="./code-09.html">09</a></li>
          <li><a href="./code-10.html">10</a></li>
          <li><a href="./code-11.html">11</a></li>
          <li><a href="./code-12.html">12</a></li>
        </ul>
      </div>
    </div>

    <footer class="uk-section uk-text-center uk-text-muted">
      <div class="uk-container uk-container-small">
        <div class="uk-margin-medium"></div>
      </div>
    </footer>

    <script src="../js/awesomplete.js"></script>
    <script src="../js/custom.js"></script>
  </body>
</html>
